package com.jiguang.property.service.impl;

import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.jiguang.property.dto.CostInfoDTO;
import com.jiguang.property.dto.CostStatiesDTO;
import com.jiguang.property.dto.UserInfoDTO;
import com.jiguang.property.entity.CostInfo;
import com.jiguang.property.entity.HostelInfo;
import com.jiguang.property.entity.UpkeepInfo;
import com.jiguang.property.entity.User;
import com.jiguang.property.mapper.CostInfoMapper;
import com.jiguang.property.service.CostInfoService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jiguang.property.service.UpkeepInfoService;
import com.jiguang.property.service.UserService;
import com.jiguang.property.utils.JwtUtils;
import com.jiguang.property.utils.RandomUtils;
import com.jiguang.property.utils.Result;
import io.netty.util.internal.StringUtil;
import lombok.SneakyThrows;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author testjava
 * @since 2025-03-27
 */
@Service
public class CostInfoServiceImpl extends ServiceImpl<CostInfoMapper, CostInfo> implements CostInfoService {
    @Autowired
    private JwtUtils tokenManager;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private UserService userService;
    @Autowired
    private JavaMailSender mailSender;
    @Autowired
    private UpkeepInfoService upkeepInfoService;

    @Value("${spring.mail.username}")
    private String from;
    @Value("${spring.mail.nickname}")
    private String nickname;

    @SneakyThrows
    @Override
    public Result listCostInfo(CostInfoDTO costInfoDTO) {
        //通过工具类获取Request对象
        ServletRequestAttributes sra = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = sra.getRequest();
        //获取用户名
        //需要通过解析token获取
        String token = request.getHeader("token");
        if (StringUtils.isEmpty(token)){
            return Result.error().code(403).message("登陆超时，请重新登陆");
        }
        String userId = tokenManager.getUserFromToken(token);

        //从redis中获取用户信息
        String redisKey = "login:" + userId;
        redisTemplate.setValueSerializer(new StringRedisSerializer());
        String cacheObject = (String) redisTemplate.opsForValue().get(redisKey);
        if (StringUtils.isEmpty(cacheObject)) {
            return Result.error().code(403).message("登陆超时，请重新登陆");
        }
        UserInfoDTO ucenter = new ObjectMapper().readValue(cacheObject.toString(), UserInfoDTO.class);

        //创建分页对象
        Page<CostInfo> page = new Page<>(costInfoDTO.getPageNow(),costInfoDTO.getPageSize());

        QueryWrapper<CostInfo> wrapper = new QueryWrapper<>();

        //判断用户的权限
        if (ucenter.getPosition() != null && (ucenter.getPosition() == 2 || ucenter.getPosition() == 1) ){
            if (StringUtils.isEmpty(costInfoDTO.getUserId())) userId = null;
            else userId = costInfoDTO.getUserId();

        }else{
            wrapper.eq("user_id",userId);
        }

        wrapper.eq("is_delete",0);
        wrapper.orderByDesc("update_time");

        Page<CostInfo> buildInfoPage = (Page<CostInfo>) baseMapper.selectPage(page,wrapper);
        return Result.ok().message("查询成功").data("costInfos", buildInfoPage.getRecords()).data("total",buildInfoPage.getTotal());
    }

    @Override
    public Result deleteHostelInfo(String costIds) {
        if (StringUtils.isEmpty(costIds)) return Result.error().message("Id不能为空");
        List<String> ids = Arrays.asList(costIds.split(","));
        baseMapper.deleteBatchIds(ids);
        return Result.ok().message("删除成功");
    }

    @SneakyThrows
    @Override
    public Result updateCostInfo(CostInfoDTO costInfoDTO) {
        if (StringUtils.isEmpty(costInfoDTO.getId())){
            return Result.error().message("ID不能为空");
        }

        //通过工具类获取Request对象
        ServletRequestAttributes sra = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = sra.getRequest();
        //获取用户名
        //需要通过解析token获取
        String token = request.getHeader("token");
        if (StringUtils.isEmpty(token)){
            return Result.error().code(403).message("登陆超时，请重新登陆");
        }
        String userId = tokenManager.getUserFromToken(token);

        //从redis中获取用户信息
        String redisKey = "login:" + userId;
        redisTemplate.setValueSerializer(new StringRedisSerializer());
        String cacheObject = (String) redisTemplate.opsForValue().get(redisKey);
        if (StringUtils.isEmpty(cacheObject)) {
            return Result.error().code(403).message("登陆超时，请重新登陆");
        }
        UserInfoDTO ucenter = new ObjectMapper().readValue(cacheObject.toString(), UserInfoDTO.class);

        //判断用户的权限
        if (ucenter.getPosition() != null && ucenter.getPosition() == 2){
            return Result.error().message("权限不足");
        }

        return Result.ok().message("修改成功");
    }

    @Override
    public Result urge(String userId,String costId) {
        //获取用户的邮箱
        User user = userService.getById(userId);
        if (user == null){
            return Result.error().message("该用户不存在");
        }

        if (user.getPosition() != 0){
            return Result.error().message("该用户不是业主");
        }

        //查询该记录的催缴次数
        CostInfo costInfo = baseMapper.selectById(costId);
        if (costInfo == null){
            return Result.error().message("不存在缴费记录");
        }
        if (costInfo.getUrgeNumber() > 0){
            return Result.ok().message("已催缴，请耐心等待");
        }


        //创建邮箱信息
        SimpleMailMessage message = new SimpleMailMessage();
        message.setFrom(nickname + '<' + from + '>');
        message.setTo(user.getEmail());
        message.setSubject("阳光小区物业工作人员：");
        message.setText("尊敬的用户"+ user.getUsername()+ "，您好：\n" +
                " \n 你存在"+ costInfo.getType() +"尚未缴纳，应缴纳费用为"+costInfo.getPrice()+"，请尽快缴纳。\n(这是一封通过自动发送的邮件，请不要直接回复）");
        mailSender.send(message);

        //修改催缴次数
        costInfo.setUrgeNumber(costInfo.getUrgeNumber()+1);
        baseMapper.updateById(costInfo);

        return Result.ok().message("已向业主发送催缴信息，请耐心等待");
    }

    @SneakyThrows
    @Override
    public Result getCostInfo() {
        //通过工具类获取Request对象
        ServletRequestAttributes sra = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = sra.getRequest();
        //获取用户名
        //需要通过解析token获取
        String token = request.getHeader("token");
        if (StringUtils.isEmpty(token)){
            return Result.error().code(403).message("登陆超时，请重新登陆");
        }
        String userId = tokenManager.getUserFromToken(token);

        //从redis中获取用户信息
        String redisKey = "login:" + userId;
        redisTemplate.setValueSerializer(new StringRedisSerializer());
        String cacheObject = (String) redisTemplate.opsForValue().get(redisKey);
        if (StringUtils.isEmpty(cacheObject)) {
            return Result.error().code(403).message("登陆超时，请重新登陆");
        }
        UserInfoDTO ucenter = new ObjectMapper().readValue(cacheObject.toString(), UserInfoDTO.class);

        int month = DateUtil.month(new Date())+1;
        QueryWrapper<CostInfo> wrapper = new QueryWrapper<>();
        wrapper.eq("is_delete",0);
        wrapper.eq("month",String.valueOf(month));
        QueryWrapper<UpkeepInfo> upWrapper = new QueryWrapper<>();
        upWrapper.eq("is_delete",0);
        upWrapper.ge("create_time",DateUtil.beginOfMonth(new Date()));
        upWrapper.le("create_time",DateUtil.endOfMonth(new Date()));
        if (ucenter.getPosition() == 4){
            return Result.ok().data("collectAdvance",0).data("received",0);
        }else if(ucenter.getPosition() == 3){
            upWrapper.eq("upkeep_id",userId);
            upWrapper.eq("status",3).or().eq("status",2);
            List<UpkeepInfo> upkeepInfoList = upkeepInfoService.list(upWrapper);
            Double collectAdvance = 0.0;
            Double received = 0.0;
            for (UpkeepInfo upkeepInfo : upkeepInfoList) {
                BigDecimal bigDecimal = new BigDecimal(Double.toString(upkeepInfo.getPrice()));
                collectAdvance = new BigDecimal(Double.toString(collectAdvance)).add(bigDecimal).doubleValue();
                if(upkeepInfo.getStatus() == 3){
                    received = new BigDecimal(Double.toString(received)).add(bigDecimal).doubleValue();
                }
            }
            return Result.ok().data("collectAdvance",collectAdvance).data("received",received);
        }else if(ucenter.getPosition() == 1 || ucenter.getPosition() == 2){
            List<CostInfo> costInfos = baseMapper.selectList(wrapper);
            Double collectAdvance = 0.0;
            Double received = 0.0;
            for (CostInfo costInfo : costInfos) {
                BigDecimal bigDecimal = new BigDecimal(Double.toString(costInfo.getPrice()));
                collectAdvance = new BigDecimal(Double.toString(collectAdvance)).add(bigDecimal).doubleValue();
                if(costInfo.getStatus() == 1){
                    received = new BigDecimal(Double.toString(received)).add(bigDecimal).doubleValue();
                }
            }
            return Result.ok().data("collectAdvance",collectAdvance).data("received",received);
        }else if(ucenter.getPosition() == 0){
            wrapper.eq("user_id",userId);
            List<CostInfo> costInfos = baseMapper.selectList(wrapper);
            Double collectAdvance = 0.0;
            Double received = 0.0;
            for (CostInfo costInfo : costInfos) {
                BigDecimal bigDecimal = new BigDecimal(Double.toString(costInfo.getPrice()));
                collectAdvance = new BigDecimal(Double.toString(collectAdvance)).add(bigDecimal).doubleValue();
                if(costInfo.getStatus() == 1){
                    received = new BigDecimal(Double.toString(received)).add(bigDecimal).doubleValue();
                }
            }

            //维修上报的费用
            upWrapper.eq("reporter_id",userId);
            upWrapper.eq("status",3).or().eq("status",2);
            List<UpkeepInfo> upkeepInfoList = upkeepInfoService.list(upWrapper);
            for (UpkeepInfo upkeepInfo : upkeepInfoList) {
                BigDecimal bigDecimal = new BigDecimal(Double.toString(upkeepInfo.getPrice()));
                collectAdvance = new BigDecimal(Double.toString(collectAdvance)).add(bigDecimal).doubleValue();
                if(upkeepInfo.getStatus() == 3){
                    received = new BigDecimal(Double.toString(received)).add(bigDecimal).doubleValue();
                }
            }

            return Result.ok().data("collectAdvance",collectAdvance).data("received",received);
        }

        return Result.ok().data("collectAdvance",0).data("received",0);
    }

    @Override
    public Result getCostInfoByMonth() {
        //通过工具类获取Request对象
        ServletRequestAttributes sra = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = sra.getRequest();
        //获取用户名
        //需要通过解析token获取
        String token = request.getHeader("token");
        if (StringUtils.isEmpty(token)){
            return Result.error().code(403).message("登陆超时，请重新登陆");
        }
        String userId = tokenManager.getUserFromToken(token);

        //从redis中获取用户信息
        String redisKey = "login:" + userId;
        redisTemplate.setValueSerializer(new StringRedisSerializer());
        String cacheObject = (String) redisTemplate.opsForValue().get(redisKey);
        if (StringUtils.isEmpty(cacheObject)) {
            return Result.error().code(403).message("登陆超时，请重新登陆");
        }
        UserInfoDTO ucenter = null;
        try {
            ucenter = new ObjectMapper().readValue(cacheObject.toString(), UserInfoDTO.class);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }

        if(ucenter.getPosition() == 4){
            return Result.ok().data("costStatiesDTOS",null);
        }else if(ucenter.getPosition() == 3){
            List<CostStatiesDTO> costStatiesDTOS = baseMapper.selectStatiesByUpkeep(userId,null);
            return Result.ok().data("costStatiesDTOS",costStatiesDTOS);
        }else if(ucenter.getPosition() == 1 || ucenter.getPosition() == 2){
            List<CostStatiesDTO> costStatiesDTOS = baseMapper.selectStatiesByCost(null);
            return Result.ok().data("costStatiesDTOS",costStatiesDTOS);
        }else if(ucenter.getPosition() == 0){
            List<CostStatiesDTO> costStatiesDTOS = baseMapper.selectStatiesByUpkeep(null,userId);
            Map<String, Double> unHashMap = new HashMap<>();
            Map<String, Double> hashMap = new HashMap<>();
            if (!CollectionUtils.isEmpty(costStatiesDTOS)){
                for (CostStatiesDTO costStatiesDTO : costStatiesDTOS) {
                    hashMap.put(costStatiesDTO.getMonth(),costStatiesDTO.getPaidAmount());
                    unHashMap.put(costStatiesDTO.getMonth(),costStatiesDTO.getUnPaidAmount());
                }
            }

            List<CostStatiesDTO> costStatiesDTOList = baseMapper.selectStatiesByCost(userId);
            if (!CollectionUtils.isEmpty(costStatiesDTOList)){
                for (CostStatiesDTO costStatiesDTO : costStatiesDTOList) {
                    BigDecimal paidAmount = hashMap.containsKey(costStatiesDTO.getMonth()) ? new BigDecimal(Double.toString(hashMap.get(costStatiesDTO.getMonth()))) : new BigDecimal("0");
                    BigDecimal unPaidAmount = unHashMap.containsKey(costStatiesDTO.getMonth()) ? new BigDecimal(Double.toString(unHashMap.get(costStatiesDTO.getMonth()))) : new BigDecimal("0");
                    hashMap.put(costStatiesDTO.getMonth(),new BigDecimal(Double.toString(costStatiesDTO.getPaidAmount())).add(paidAmount).doubleValue());
                    unHashMap.put(costStatiesDTO.getMonth(),new BigDecimal(Double.toString(costStatiesDTO.getUnPaidAmount())).add(unPaidAmount).doubleValue());
                }
            }

            Set<String> monthSet = hashMap.keySet();
            if(CollectionUtils.isEmpty(monthSet)){return Result.ok().data("costStatiesDTOS",null);}
            List<CostStatiesDTO> costStatiesNewDTO = new ArrayList<>();
            monthSet.stream().forEach(month ->{
                CostStatiesDTO costStatiesDTO = new CostStatiesDTO();
                costStatiesDTO.setMonth(month);
                costStatiesDTO.setPaidAmount(hashMap.getOrDefault(month,0.0));
                costStatiesDTO.setUnPaidAmount(unHashMap.getOrDefault(month,0.0));
                costStatiesNewDTO.add(costStatiesDTO);
            });

            return Result.ok().data("costStatiesDTOS",costStatiesNewDTO);
        }
        return Result.ok().data("upkeepNumber",0).data("waitSolve",0);
    }

//    /**
//     * 新增账单
//     */
//    public void addCost(CostInfo costInfo){
//        baseMapper.insert(costInfo);
//    }
}
